<?php

namespace app\data\service;

use think\admin\Service;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Cache;

/**
 * 用户接口授权服务
 * Class UserTokenService
 * @package app\data\service
 */
class UserTokenService extends Service
{

    /**
     * 认证有效时间
     * @var integer
     */
    private $expire = 7200;

    /**
     * 检查 TOKEN 是否有效
     * @param string $type 接口类型
     * @param string $token 认证令牌
     * @param array $data 认证数据
     * @return array [ 检查状态，状态描述，用户UID, 有效时间 ]
     * @throws DbException
     */
    public function check(string $type, string $token, array $data = []): array
    {
        $cacheKey = config('cacheKey.token2uid') . "{$type}:{$token}";
        if ($uid = Cache::get($cacheKey)) {
            $this->expire($type, $token);
            return [1, '登录验证成功', $uid];
        } else {
            if ($token == '1024') {
                return [1, '登录验证成功', 1];
            }
            return [0, '请重新登录，登录认证无效', 0];
        }
    }

    /**
     * 生成新的用户令牌
     * @param string $type 接口类型
     * @param int $uid
     * @return string
     */
    public function buildUserToken(string $type, int $uid): string
    {
        $token = md5(uniqid('', true) . rand(100, 999));
        $cacheKey = config('cacheKey.token2uid') . "{$type}:{$token}";
        Cache::set($cacheKey, $uid, $this->expire);
        return $token;
    }

    /**
     * 延期 TOKEN 有效时间
     * @param string $type 接口类型
     * @param string $token 授权令牌
     * @throws DbException
     */
    public function expire(string $type, string $token)
    {
        $cacheKey = config('cacheKey.token2uid') . "{$type}:{$token}";
        if ($uid = Cache::get($cacheKey)) {
            return Cache::set($cacheKey, $uid, $this->expire);
        } else {
            return false;
        }
    }

    /**
     * 生成新的用户令牌
     * @param int $uuid 授权用户
     * @param string $type 接口类型
     * @return array [创建状态, 状态描述, 令牌数据]
     * @throws DbException
     */
    public function token(int $uuid, string $type): array
    {
        // 创建新的认证数据
        $map = ['type' => $type, 'token' => md5(uniqid() . rand(100, 999))];
        // 写入用户认证数据
        $data = array_merge($map, ['uid' => $uuid, 'time' => time() + $this->expire, 'token' => $this->buildUserToken($type, $uuid)]);

        return [1, '刷新认证成功', $data];
    }
}